import {Promise} from 'es6-promise';
import {Collection, ObjectID} from "mongodb";

import * as utils from '../core/utils';
import {Magics} from "../core/magics";
import {CursorType} from "../core/defines";
import {MongoColls} from '../config/mongo';
import {ErrCode} from "../core/error.code";
import {BaseModel} from "../core/base.model";
import {
    FindParam,
    CountParam,
    UpdateParam,
    FindOneParam,
    FindOneUpdateParam,
} from "../core/params";

export enum FavoriteStatus {
    CREATED = 1,
    INVALID = 2,
    DELETED = 3
}

export enum FavoriteType {
    PRODUCT = 1,
    ARTICLE = 2,
    SHOP = 3,
}

export interface FavoriteInfo {
    _id ?: ObjectID,
    user_id: ObjectID,
    src_id: ObjectID,
    type: FavoriteType,
    status?: FavoriteStatus,
    detail?: Object,
    time ?: Date
}

export interface FavorFilter {
    _id ?: ObjectID,
    user_id?: ObjectID,
    src_id?: ObjectID,
    type?: FavoriteType,
    page?: number,
    limit?: number,
}

export default class FavoriteModel extends BaseModel {
    constructor(coll: Collection) {
        super(coll);
    }

    name() {
        return 'FavoriteModel';
    }

    checkExist(filter: FavorFilter): Promise<any> {
        let match = {
            user_id: filter.user_id,
            src_id: filter.src_id,
            status: {'$ne': FavoriteStatus.DELETED}
        };
        return this.findOne(new FindOneParam(match));
    }

    addToFavorite(filter: FavorFilter, info: FavoriteInfo): Promise<any> {
        let match = {
            user_id: filter.user_id,
            src_id: filter.src_id
        };

        info.status = FavoriteStatus.CREATED;
        info.time = new Date();
        return this.findOneAndUpdate(new FindOneUpdateParam(match, {$set: info}, true));
    };

    deleteFavorite(filter: FavorFilter): Promise<any> {
        let match = {
            src_id: filter.src_id,
            user_id: filter.user_id
        };

        let update = {
            $set: {
                status: FavoriteStatus.DELETED
            }
        };
        return this.updateOne(new UpdateParam(match, update));
    };

    getFavorites(filter: FavorFilter): Promise<any> {
        let {user_id, type, page, limit} = filter;

        let match = {
            user_id, type
        };

        let count;
        return this.count(new CountParam(match)).then((totalCount) => {
            count = totalCount;
            let options = new FindParam(match, {});
            options.sort = {'time': -1};
            options.skip = page * limit;
            options.limit = limit;
            return this.find(options);
        }).then((records) => {
            return {
                limit,
                curr_page: page,
                total_count: count,
                records: records || [],
                total_page: Math.ceil(count / limit)
            };
        });
    };

}